package p.ithorns.framework.common.tree;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 树型结构递归嵌套工具
 *
 * @author WeiZiDong
 */
public class TreeUtil {
    /**
     * 构建节点树
     *
     * @param list          节点列表
     * @param predicate     父节点过滤函数
     * @param setChildrenFn 设置子节点函数
     * @param fun           子节点过滤函数
     * @author WeiZiDong
     */
    public static <T> List<T> build(List<T> list, Predicate<T> predicate,
                                    BiConsumer<T, List<T>> setChildrenFn,
                                    Function<T, List<T>> fun) {
        List<T> trees = list.stream().filter(predicate).collect(Collectors.toList());
        trees.forEach(t -> findChildren(t, setChildrenFn, fun));
        return trees;
    }

    /**
     * 查找子节点
     *
     * @param t             当前节点
     * @param setChildrenFn 设置子节点函数
     * @param fun           子节点过滤函数
     * @author WeiZiDong
     */
    private static <T> void findChildren(T t,
                                         BiConsumer<T, List<T>> setChildrenFn,
                                         Function<T, List<T>> fun) {
        List<T> list = fun.apply(t);
        if (list != null && !list.isEmpty()) {
            setChildrenFn.accept(t, list);
            list.forEach(it -> findChildren(it, setChildrenFn, fun));
        }
    }

}